﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.AccessControl;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Windows.Forms;
using Org.Flowertwig;

namespace SetupExtractor
{
    public partial class Form1 : Form
    {
        private string _installDirectory;
        protected string InstallDirectory
        {
            get { return _installDirectory; }
            set
            {
                _installDirectory = value;
                label2.Text = _installDirectory;
            }
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            AdminRequired(Install, "--install:" + Convert.ToBase64String(Encoding.UTF8.GetBytes(InstallDirectory)));
            Close();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Close();
        }

        private static void AdminRequired(Action actionThatMayRequiresAdminPrivileges, string cmdLine)
        {
            var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            if (principal.IsInRole(WindowsBuiltInRole.Administrator) == false)
            {
                if (RunAgainAsAdmin(cmdLine))
                    return;
            }
            actionThatMayRequiresAdminPrivileges();
        }

        private static bool RunAgainAsAdmin(string cmdLine)
        {
            try
            {
                var process = Process.Start(new ProcessStartInfo
                {
                    Arguments = cmdLine,
                    FileName = Assembly.GetExecutingAssembly().Location,
                    Verb = "runas",
                });
                //process.WaitForExit();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
        private void Install()
        {
            if (!Directory.Exists(InstallDirectory))
            {
                try
                {
                    Directory.CreateDirectory(InstallDirectory);
                }
                catch (UnauthorizedAccessException ex)
                {
                    MessageBox.Show(string.Format("You are not authorized to install this application in '{0}.'", InstallDirectory));
                    return;
                }
            }

            var fg = new FileGenerator();
            fg.WriteTo(InstallDirectory);

            var di = new DirectoryInfo(InstallDirectory);
            var files = di.GetFiles("Setup.exe");
            if (files.Length > 0)
            {
                var setupFile = files.FirstOrDefault();
                if (setupFile != null)
                {
                    Process.Start(setupFile.FullName);

                    Close();
                    return;
                }
            }

            MessageBox.Show("Unknown error occured while trying to extract setup files.");
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                InstallDirectory = folderBrowserDialog1.SelectedPath;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            const string installArgName = "--install:";
            var installArg =  Environment.GetCommandLineArgs().FirstOrDefault(str => str.StartsWith(installArgName));
            if (!string.IsNullOrEmpty(installArg))
            {
                var instDir = Encoding.UTF8.GetString(Convert.FromBase64String(installArg.Substring(installArgName.Length)));
                InstallDirectory = instDir;
                AdminRequired(Install, installArg);
                Close();
                return;
            }

            var directory = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
            InstallDirectory = directory + Path.DirectorySeparatorChar + "FlowMedia" + Path.DirectorySeparatorChar;
        }
    }
}
